package developer.zyk.starter.controllers.chat;

import developer.zyk.ability.chat.dao.entity.ChatHistoryDO;
import developer.zyk.ability.chat.dao.entity.ChatHistoryDetailDO;
import developer.zyk.ability.chat.param.ChatAppendMessageParam;
import developer.zyk.ability.chat.param.ChatDetailSearchParam;
import developer.zyk.ability.chat.param.ChatHistoryCreateParam;
import developer.zyk.ability.chat.param.ChatHistorySearchParam;
import developer.zyk.ability.chat.service.ChatHistoryService;
import developer.zyk.ability.chat.template.ChatTemplate;
import developer.zyk.ability.config.AIProperties;
import developer.zyk.global.common.Result;
import developer.zyk.starter.controllers.chat.vo.ChatDetailVO;
import developer.zyk.starter.controllers.chat.vo.ChatHistorySummaryVO;
import lombok.AllArgsConstructor;
import org.springframework.web.bind.annotation.*;
import reactor.core.publisher.Flux;

import javax.validation.Valid;
import java.time.LocalDate;
import java.util.*;
import java.util.function.Function;
import java.util.stream.Collectors;

@RestController()
@RequestMapping("chat")
@AllArgsConstructor
public class ChatController {
    private ChatHistoryService chatHistoryService;
    private ChatTemplate chatTemplate;
    private AIProperties aiProperties;

    @PostMapping("createNewChat")
    public Result<Long> createNewChat(@Valid @RequestBody ChatHistoryCreateParam chatHistoryCreateParam) {
        return Result.success(chatHistoryService.addNewChat(chatHistoryCreateParam));
    }


    @PostMapping("delete/{id}")
    public Result<Boolean> delete(@PathVariable Long id) {
        return Result.success(chatHistoryService.deleteById(id));
    }


    @PostMapping("historySummary")
    public Result<List<ChatHistorySummaryVO>> historySummary(@RequestBody ChatHistorySearchParam chatHistorySearchParam) {
        List<ChatHistoryDO> chatHistory = chatHistoryService.findChatHistory(chatHistorySearchParam.getOperateId());

        Map<String, AIProperties.ModelInfo> modelTypeMap = aiProperties.getSupportModel().getModels().stream()
                .collect(Collectors.toMap(AIProperties.ModelInfo::getKey, Function.identity(), (a, b) -> b));

        List<ChatHistorySummaryVO> result = chatHistory.stream()
                .collect(Collectors.groupingBy(a -> a.getGmtCreate().toLocalDate()))
                .entrySet()
                .stream()
                .map(entry -> {
                    LocalDate key = entry.getKey();
                    List<ChatHistorySummaryVO.ChatHistory> datas = entry.getValue()
                            .stream()
                            .filter(Objects::nonNull)
                            .sorted(Comparator.comparing(ChatHistoryDO::getGmtCreate).reversed())
                            .map(b -> new ChatHistorySummaryVO.ChatHistory(b.getId(),
                                    b.getTitle(),
                                    Optional.of(modelTypeMap)
                                            .map(map -> map.get(b.getModelType()))
                                            .map(c->c.getLabel())
                                            .orElse(b.getModelType())
                            ))
                            .collect(Collectors.toList());

                    ChatHistorySummaryVO.GroupInfo groupInfo = new ChatHistorySummaryVO.GroupInfo();
                    groupInfo.setDate(key);

                    ChatHistorySummaryVO chatHistorySummaryVO = new ChatHistorySummaryVO();
                    chatHistorySummaryVO.setDatas(datas);
                    chatHistorySummaryVO.setGroupInfo(groupInfo);
                    return chatHistorySummaryVO;
                }).
                sorted((a, b) -> {
                    LocalDate ad = a.getGroupInfo().getDate();
                    LocalDate bd = b.getGroupInfo().getDate();
                    return bd.compareTo(ad);
                }).
                toList();

        return Result.success(result);
    }

    @PostMapping("detail")
    public Result<ChatDetailVO> chatDetail(@RequestBody ChatDetailSearchParam param) {
        ChatHistoryDO chatInfo = chatHistoryService.findChatByChatId(param.getChatId());
        List<ChatHistoryDetailDO> chatDetailInfos = chatHistoryService.findChatDetailByChatId(param.getChatId());
        return Result.success(ChatDetailVO.of(chatInfo, chatDetailInfos));
    }


    @PostMapping("appendMessage")
    public Flux<String> appendMessage(@RequestBody ChatAppendMessageParam chatAppendMessageParam) {
        return chatTemplate.appendMessage(chatAppendMessageParam);
    }

}
